/**
 * @File   : exportExcel.js
 * @Author : xf (953983040@qq.com)
 * @Link   :
 * @Date   : 2017-10-12 19:37:29
 *
    {
      datas:[]  ,//导出的数据
      fileName: '信息.xlsx', //导出文件名
      headers: [],   //标题对象数组  {v:'',name:''} 格式
      dataFunc: function() {   //导出全部的查询方法
      },
      params: [], //查询参数  需要安照function的参数顺序
      dataFunc2: function() { //导出全部的分页查询方法
      },
      params2: [] //分页查询参数 需要安照function的参数顺序
  }
 *
 */
// 步骤：

// 构建特定的数据结构，如下。
// 调用 XLSX.writeFile(workbook, filename) 即可。
// // workbook
// {
//     SheetNames: ['mySheet'],
//     Sheets: {
//         'mySheet': {
//             '!ref': 'A1:E4', // 必须要有这个范围才能输出，否则导出的 excel 会是一个空表
//             A1: { v: 'id' },
//             ...
//         }
//     }
// }
import XLSX from "xlsx"
import ResTypeEnum from 'common/resTypeEnum'
export default {
    exportAll(obj) {
        const self = this
        let p = new Promise(function(resolve, reject) {
            self.getData(1, obj).then((success) => {
                    resolve(success);
                })
                .catch((err) => {
                    reject(err);
                })
        });
        console.log('excel:exportAll');
        return p
    },
    exportCurrent(obj) {
        const self = this
        let p = new Promise(function(resolve, reject) {
            self.getData(2, obj).then((success) => {
                    resolve(success);
                })
                .catch((err) => {
                    reject(err);
                })
        });
        console.log('excel:exportCurrent');
        return p
    },
    getData(type, obj) {
        const self = this
        let p = new Promise(
            function(resolve, reject) {
                if (obj.datas instanceof Array && obj.datas.length > 0) {
                    self.down(obj, self.parseData(obj), 'xlsx');
                    resolve('success');
                    return p
                }
                if (obj.dataFunc instanceof Function && type == 1) {
                    obj.dataFunc.apply(null, obj.params).then(response => {
                        let data = response.data;
                        if (data instanceof Array) {
                            obj.datas = data
                        } else if (data instanceof Object) {
                            obj.datas = data.rows
                        }
                        if (obj.datas instanceof Array && obj.datas.length > 0) {
                            self.down(obj, self.parseData(obj), 'xlsx');
                        }
                        obj.datas = []
                        resolve('success');
                    }).catch(err => {
                        console.log(err)
                        reject(err);
                    });
                } else if (obj.dataFunc2 instanceof Function && type == 2) {
                    obj.dataFunc2.apply(null, obj.params2).then(response => {
                        let data = response.data;
                        if (data instanceof Array) {
                            obj.datas = data
                        } else if (data instanceof Object) {
                            obj.datas = data.rows
                        }
                        if (obj.datas instanceof Array && obj.datas.length > 0) {
                            self.down(obj, self.parseData(obj), 'xlsx');
                        }
                        obj.datas = []
                        resolve('success');
                    }).catch(err => {
                        console.log(err)
                        reject(err);
                    });
                } else {
                    resolve('failed');
                }
            }
        );
        return p
    },
    parseData(obj) {
        const self = this
        let header = obj.headers
            // 为 header 添加对应的单元格位置
            // [ { v: 'id', position: 'A1' },
            //   { v: 'name', position: 'B1' },
            //   { v: 'age', position: 'C1' },
            //   { v: 'country', position: 'D1' },
            //   { v: 'remark', position: 'E1' } ]
            .map((v, i) => Object.assign({}, { v: v.v, name: v.name, position: String.fromCharCode(65 + i) + 1 }))
            // 转换成 worksheet 需要的结构
            // { A1: { v: 'id' },
            //   B1: { v: 'name' },
            //   C1: { v: 'age' },
            //   D1: { v: 'country' },
            //   E1: { v: 'remark' } }
        let _headers = header.reduce((prev, next) => Object.assign({}, prev, {
            [next.position]: { v: next.name }
        }), {});
        let data = obj.datas
            // 匹配 header 的位置，生成对应的单元格数据
            // [ [ { v: '1', position: 'A2' },
            //     { v: 'test1', position: 'B2' },
            //     { v: '30', position: 'C2' },
            //     { v: 'China', position: 'D2' },
            //     { v: 'hello', position: 'E2' } ],
            //   [ { v: '2', position: 'A3' },
            //     { v: 'test2', position: 'B3' },
            //     { v: '20', position: 'C3' },
            //     { v: 'America', position: 'D3' },
            //     { v: 'world', position: 'E3' } ],
            //   [ { v: '3', position: 'A4' },
            //     { v: 'test3', position: 'B4' },
            //     { v: '18', position: 'C4' },
            //     { v: 'Unkonw', position: 'D4' },
            //     { v: '???', position: 'E4' } ] ]
            .map(function(v, i) {
                let row = []
                for (let j = 0; j < header.length; j++) {
                    let k = header[j]
                    let val = v[k.v]
                    val = self.filterVal(val, k, i)
                    let obj = {
                        v: val ? val : '',
                        position: String.fromCharCode(65 + j) + (i + 2)
                    }
                    row.push(obj)
                }
                return row
            })
            // (v, i) => header.map((k, j) => Object.assign({}, { v: v[k.v], position: String.fromCharCode(65+j) + (i+2) })))
        data = data
            // 对刚才的结果进行降维处理（二维数组变成一维数组）
            // [ { v: '1', position: 'A2' },
            //   { v: 'test1', position: 'B2' },
            //   { v: '30', position: 'C2' },
            //   { v: 'China', position: 'D2' },
            //   { v: 'hello', position: 'E2' },
            //   { v: '2', position: 'A3' },
            //   { v: 'test2', position: 'B3' },
            //   { v: '20', position: 'C3' },
            //   { v: 'America', position: 'D3' },
            //   { v: 'world', position: 'E3' },
            //   { v: '3', position: 'A4' },
            //   { v: 'test3', position: 'B4' },
            //   { v: '18', position: 'C4' },
            //   { v: 'Unkonw', position: 'D4' },
            //   { v: '???', position: 'E4' } ]
            .reduce((prev, next) => prev.concat(next))
        let datar = data
            // 转换成 worksheet 需要的结构
            //   { A2: { v: '1' },
            //     B2: { v: 'test1' },
            //     C2: { v: '30' },
            //     D2: { v: 'China' },
            //     E2: { v: 'hello' },
            //     A3: { v: '2' },
            //     B3: { v: 'test2' },
            //     C3: { v: '20' },
            //     D3: { v: 'America' },
            //     E3: { v: 'world' },
            //     A4: { v: '3' },
            //     B4: { v: 'test3' },
            //     C4: { v: '18' },
            //     D4: { v: 'Unkonw' },
            //     E4: { v: '???' } }
            .reduce((prev, next) => Object.assign({}, prev, {
                [next.position]: { v: next.v }
            }), {});
        // 合并 header 和 data
        let output = Object.assign({}, _headers, datar);
        // 获取所有单元格的位置
        let outputPos = Object.keys(output);
        // 计算出范围
        let ref = outputPos[0] + ':' + outputPos[outputPos.length - 1];

        // 构建 workbook 对象
        let wb = {
            SheetNames: ['mySheet'],
            Sheets: {
                'mySheet': Object.assign({}, output, { '!ref': ref })
            }
        };
        return wb
    },
    down(obj, wb, type) {
        const self = this
        let tmpDown = new Blob([self.s2ab(XLSX.write(wb, { bookType: (type == undefined ? 'xlsx' : type), bookSST: false, type: 'binary' } //这里的数据是用来定义导出的格式类型
        ))], { type: "" }); //创建二进制对象写入转换好的字节流

        var href = URL.createObjectURL(tmpDown); //创建对象超链接
        let a = document.createElement('a')
        a.href = href //绑定a标签
        a.download = obj.fileName
        a.target = '_blank'
        let body = document.getElementsByTagName('body')[0]
        body.appendChild(a)
        a.click() //模拟点击实现下载
        setTimeout(function() { //延时释放a
            body.removeChild(a)
        }, 300)
        setTimeout(function() { //延时释放
            URL.revokeObjectURL(tmpDown); //用URL.revokeObjectURL()来释放这个object URL
        }, 100);
    },
    s2ab(s) { //字符串转字符流
        var buf = new ArrayBuffer(s.length);
        var view = new Uint8Array(buf);
        for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
        return buf;
    },
    filterVal(val, k, index) {
        const self = this
        if ((k.v == 'clock' || k.v == 'time' || k.name == '最新时间') && parseInt(val) > 0) {
            val = val + ''
            if (val.length == 10) {
                val = self.formatDate(parseInt(val) * 1000)
            } else if (val.indexOf(':') > -1) {
                val = val
            } else {
                val = self.formatDate(parseInt(val))
            }
        }
        if ((/^(\+|-)?\d+$/.test(val)) && k.name == '资源') {
            val = ResTypeEnum.getAuditResourceToStr(parseInt(val))
        }
        if ((/^(\+|-)?\d+$/.test(val)) && k.name == '动作') {
            val = ResTypeEnum.getAuditActionToStr(parseInt(val))
        }
        if (k.name == '细节') {
            val = val == '0' ? '' : val
        }

        if ((/^(\+|-)?\d+$/.test(val)) && k.v == 'clevel') {
            val = ResTypeEnum.getAlarmSeverityLevel(parseInt(val)).label
        }

        if (k.name == '序号') {
            val = (index ? index : 0) + 1
        }
        return val
    },
    formatDate(time) {
        if (time == null) {
            return "未知时间";
        }
        let tmpDate = new Date(time)
        let year = tmpDate.getFullYear()
        let mathon = tmpDate.getMonth() + 1
        let day = tmpDate.getDate()
        let hours = tmpDate.getHours()
        let minutes = tmpDate.getMinutes()
        return year + '-' + mathon + '-' + day + ' ' + hours + ':' + minutes
    }
}